#include	<gtest/gtest.h>
#include	<string>
#include	<stdio.h>
#include	"../dlist.h"

static int cmp_func(void *ctxt, void *data)
{
	return *(int *)ctxt == *(int *)data; 
}

static void int_destroy_func(void *ctxt, void *data)
{
	free(data);
	data = NULL;
}

static void *int_alloc_func(void *ctxt, size_t size)
{
	return malloc(size); 
}

static void int_print_func(void *ctxt, void *data)
{
	printf("%d ", *(int *)data);
}

TEST(list,one_entry)
{
	DList *list = dlist_create(sizeof(int), NULL, NULL, NULL);
	EXPECT_EQ(list != NULL, 1);

	int i, j, result;
	i = 4; j = 4;

	/* push one entry */
	dlist_push_front(list, &i);
	EXPECT_EQ(dlist_count(list), 1);

	DListIter start = dlist_head(list);
	DListIter end = dlist_tail(list);
	DListIter *entry = dlist_find(list, start, ++end, 
			DIRECT_FORWARD, cmp_func, &j);
	result = get_entry_value(dlist, list, entry, int);
	EXPECT_EQ(result, 4);

	dlist_for_each(list, start, ++end, 
			DIRECT_FORWARD, int_print_func, NULL);

	dlist_pop_back(list);
	EXPECT_EQ(dlist_count(list), 0);

	DListIter start = dlist_head(list);
	DListIter end = dlist_tail(list);
	DListIter *entry = dlist_find(list, start, ++end, 
			DIRECT_FORWARD, cmp_func, &j);
	EXPECT_EQ(entry == NULL, 1);

	dlist_destroy(list);
}

TEST(list,two_entry)
{
	DList *list = dlist_create(sizeof(int), 
			int_alloc_func, int_destroy_func, NULL);
	EXPECT_EQ(list != NULL, 1);

	int i, j, t, result;
	i = 4; j = 5; t = 5;

	/* push two entry */
	dlist_push_front(list, &i);
	dlist_push_front(list, &j);
	EXPECT_EQ(dlist_count(list), 2);

	DListIter start = dlist_head(list);
	DListIter end = dlist_tail(list);
	DListIter *entry = dlist_find(list, start, ++end, 
			DIRECT_FORWARD, cmp_func, &j);
	result = get_entry_value(dlist, list, entry, int);
	EXPECT_EQ(result, t);

	dlist_for_each(list, start, ++end, 
			DIRECT_FORWARD, int_print_func, NULL);

	dlist_remove(list, entry);
	EXPECT_EQ(dlist_count(list), 1);

	dlist_pop_back(list);
	EXPECT_EQ(dlist_count(list), 0);

	DListIter start = dlist_head(list);
	DListIter end = dlist_tail(list);
	DListIter *entry = dlist_find(list, start, ++end, 
			DIRECT_FORWARD, cmp_func, &j);
	EXPECT_EQ(entry == NULL, 1);

	dlist_destroy(list);
}


TEST(list,list_struct_data)
{
	DList *list = dlist_create(sizeof(std::string), 
			int_alloc_func, int_destroy_func, NULL);
	EXPECT_EQ(list != NULL, 1);

	std::string i, j, t, result;
	i = "abc"; j = "def"; t = "def";

	/* push two entry */
	dlist_push_front(list, &i);
	dlist_push_front(list, &j);
	EXPECT_EQ(dlist_count(list), 2);

	DListIter start = dlist_head(list);
	DListIter end = dlist_tail(list);
	DListIter *entry = dlist_find(list, start, ++end, 
			DIRECT_FORWARD, cmp_func, &j);
	result = get_entry_value(dlist, list, entry, int);
	EXPECT_EQ(result, t);
	entry = next_entry(dlist, list, entry);
	result = get_entry_value(dlist, list, entry, int);
	EXPECT_EQ(result, t);

	dlist_for_each(list, start, ++end, 
			DIRECT_FORWARD, int_print_func, NULL);

	dlist_remove(list, entry);
	EXPECT_EQ(dlist_count(list), 1);

	dlist_pop_back(list);
	EXPECT_EQ(dlist_count(list), 0);

	DListIter start = dlist_head(list);
	DListIter end = dlist_tail(list);
	DListIter *entry = dlist_find(list, start, ++end, 
			DIRECT_FORWARD, str_cmp_func, &j);
	EXPECT_EQ(entry == NULL, 1);

	dlist_destroy(list);
}

int main(int argc,char** argv)
{
	testing::InitGoogleTest(&argc,argv);
	return RUN_ALL_TESTS();
}
